home *** CD-ROM | disk | FTP | other *** search
/ Amiga Collections: Camelot / Camelot 043 (1989-06)(Swedish User Group of Amiga)(SE)(PD)[WB].zip / Camelot 043 (1989-06)(Swedish User Group of Amiga)(SE)(PD)[WB].adf / zc / tok.c < prev    next >
C/C++ Source or Header  |  1989-03-08  |  11KB  |  726 lines

  1. /* Copyright (c) 1988 by Sozobon, Limited.  Author: Johann Ruegg
  2.  *
  3.  * Permission is granted to anyone to use this software for any purpose
  4.  * on any computer system, and to redistribute it freely, with the
  5.  * following restrictions:
  6.  * 1) No charge may be made other than reasonable charges for reproduction.
  7.  * 2) Modified versions must be clearly marked as such.
  8.  * 3) The authors are not responsible for any harmful consequences
  9.  *    of using this software, even if they result from defects in it.
  10.  *
  11.  *    tok.c
  12.  *
  13.  *    Basic level token routines
  14.  *
  15.  *    At this level, we return the following things:
  16.  *        id's - strings of alpha-alnum
  17.  *        integer constants
  18.  *        float constants
  19.  *        string constants
  20.  *        multi-char tokens
  21.  *
  22.  *    We DONT know about:
  23.  *        keywords
  24.  *        #defined id's
  25.  *        any other meaning of a name
  26.  *
  27.  *    Interface:
  28.  *        call nxttok() to get next token
  29.  *        look at 'curtok' for current token
  30.  *        note that curtok.name points to a static area
  31.  *          for ID or SCON
  32.  *
  33.  *        if EOF is seen, we call endfile() before
  34.  *          giving up
  35.  *
  36.  *    Special flags:  (tk_flags)
  37.  *        These special flags are needed for the pre-processor.
  38.  *        All but TK_SEENL are 1-shot.
  39.  *
  40.  *        TK_SEENL - want to see \n
  41.  *        TK_WS - want to see white space (for #define)
  42.  *        TK_NOESC - dont do '\' escapes in strings
  43.  *        TK_LTSTR - '<' is a string starter
  44.  *        TK_ONLY1 - skip to token after \n  (for #if--)
  45.  */
  46.  
  47. #include <stdio.h>
  48. #include "param.h"
  49. #include "tok.h"
  50.  
  51. #ifdef dLibs
  52. #include <ctype.h>
  53. #endif
  54.  
  55. struct tok curtok;
  56. char curstr[MAXSTR+1];
  57.  
  58. #define TK_SEENL    1    /* want to see NL token */
  59. #define TK_SEEWS    2    /* want to see WS token */
  60. #define TK_ONLY1    4    /* only want 1st token on line */
  61. #define TK_LTSTR    8    /* '<' starts a string */
  62. #define TK_NOESC    16    /* dont do '\' escapes in string */
  63.  
  64. int tk_flags, sawnl;
  65.  
  66. extern FILE *input;
  67. extern int lineno;
  68.  
  69. #define NOCHAR    0x100
  70.  
  71. #ifdef DEBUG
  72. extern int oflags[];
  73. #define debug oflags['b'-'a']
  74. #endif
  75.  
  76. nxttok()
  77. {
  78.     register struct tok *t;
  79.     char *getname();
  80.     long getnumber();
  81.     register int c;
  82.     double getfrac();
  83.  
  84.     t = &curtok;
  85.     t->name = curstr;
  86.     t->name[0] = 0;
  87.     t->prec = 0;
  88.     t->flags = 0;
  89. more:
  90.     c = mygetchar();
  91.     if (c == EOF) {
  92.         tk_flags = 0;
  93.         return 0;
  94.     }
  95.     if (c == '\n') {
  96.         tk_flags &= ~TK_ONLY1;
  97.         if ((tk_flags & TK_SEENL) == 0)
  98.             goto more;
  99.         t->tnum = NL;
  100.         t->name = "\n";
  101.         goto out;
  102.     }
  103.     if (tk_flags & TK_ONLY1)
  104.         goto more;
  105.     if (c <= ' ') {
  106.         if ((tk_flags & TK_SEEWS) == 0)
  107.             goto more;
  108.         t->tnum = WS;
  109.         t->name = " ";
  110.         goto out;
  111.     }
  112.     if (c >= '0' && c <= '9') {
  113.         t->tnum = ICON;
  114.         t->ival = getnumber(c);
  115.         if (lookfrac(t->ival) || lookexp(t->ival,0.0))
  116.             goto out;
  117.     moresuf:
  118.         c = mygetchar();
  119.         if (tolower(c) == 'l') {
  120.             t->flags |= SEE_L;
  121.             goto moresuf;
  122.         } else if (tolower(c) == 'u') {
  123.             t->flags |= SEE_U;
  124.             goto moresuf;
  125.         } else {
  126.             myungetc(c);
  127.         }
  128.         sprintf(curstr, "%ld",
  129.             t->ival);
  130.         goto out;
  131.     }
  132.     if (isalpha(c) || c == '_') {
  133.         t->tnum = ID;
  134.         t->name = getname(c);
  135.         goto out;
  136.     }
  137.     if (c == '.') {
  138.         c = mygetchar();
  139.         if (c >= '0' && c <= '9') {
  140.             gotfrac(0L, getfrac(c));
  141.             goto out;
  142.         } else {
  143.             myungetc(c);
  144.             matchop('.');
  145.             goto out;
  146.         }
  147.     }
  148.     if(matchop(c) == 0)
  149.         goto more;
  150. out:
  151.     if (debug) printf("<%s>", t->name);
  152.     tk_flags &= TK_SEENL;    /* all but SEENL are 1-shot */
  153.     return 1;
  154. }
  155.  
  156. long
  157. getnumber(c)
  158. register int c;
  159. {
  160.     register long val = 0;
  161.     int base, i;
  162.  
  163.     if (c == '0') {
  164.         base = 8;
  165.     } else {
  166.         base = 10;
  167.         val = c - '0';
  168.     }
  169. more:
  170.     c = mygetchar();
  171.     if (c == EOF)
  172.         return val;
  173.     if (tolower(c) == 'x' && val == 0) {
  174.         base = 16;
  175.         goto more;
  176.     }
  177.     if (c >= '0' && c <= '9') {
  178.         val = base*val + (c - '0');
  179.         goto more;
  180.     }
  181.     if (base == 16 && (i = ishexa(c))) {
  182.         val = 16*val + i;
  183.         goto more;
  184.     }
  185.     myungetc(c);
  186.     return val;
  187. }
  188.  
  189. double
  190. getfrac(c)
  191. register c;
  192. {
  193.     register double val;
  194.     register double dig = 0.1;
  195.  
  196.     val = dig * (c - '0');
  197. more:
  198.     c = mygetchar();
  199.     if (c >= '0' && c <= '9') {
  200.         dig = .1 * dig;
  201.         val += dig * (c - '0');
  202.         goto more;
  203.     }
  204.     myungetc(c);
  205.     return val;
  206. }
  207.  
  208. lookfrac(intpart)
  209. long intpart;
  210. {
  211.     int c;
  212.     double frac;
  213.  
  214.     c = mygetchar();
  215.     if (c != '.') {
  216.         myungetc(c);
  217.         return 0;
  218.     }
  219.     c = mygetchar();
  220.     if (c >= '0' && c <= '9') {
  221.         frac = getfrac(c);
  222.     } else {
  223.         myungetc(c);
  224.         frac = 0.0;
  225.     }
  226.     gotfrac(intpart, frac);
  227.     return 1;
  228. }
  229.  
  230. gotfrac(intpart, frac)
  231. long intpart;
  232. double frac;
  233. {
  234.     if (lookexp(intpart, frac) == 0)
  235.         makeflt(intpart, frac, 0);
  236. }
  237.  
  238. lookexp(intpart, frac)
  239. long intpart;
  240. double frac;
  241. {
  242.     int c;
  243.     int minus;
  244.     int exp;
  245.  
  246.     minus = 0;
  247.     c = mygetchar();
  248.     if (tolower(c) != 'e') {
  249.         myungetc(c);
  250.         return 0;
  251.     }
  252.     c = mygetchar();
  253.     if (c == '-') {
  254.         minus = 1;
  255.         c = mygetchar();
  256.     } else if (c == '+')
  257.         c = mygetchar();
  258.     if (c >= '0' && c <= '9') {
  259.         exp = getnumber(c);
  260.     } else {
  261.         exp = 0;
  262.         myungetc(c);
  263.     }
  264.     if (minus)
  265.         exp = -exp;
  266.     makeflt(intpart, frac, exp);
  267.     return 1;
  268. }
  269.  
  270. makeflt(intpart, frac, exp)
  271. long intpart;
  272. double frac;
  273. {
  274.     register double val;
  275.     double mod, mod10, mod100;
  276.     register struct tok *t;
  277.  
  278.     val = intpart + frac;
  279.     if (exp > 0) {
  280.         mod = 1e1;
  281.         mod10 = 1e10;
  282. #if IEEE_FP
  283.         mod100 = 1e100;
  284. #endif
  285.     } else if (exp < 0) {
  286.         mod = 1e-1;
  287.         mod10 = 1e-10;
  288. #if IEEE_FP
  289.         mod100 = 1e-100;
  290. #endif
  291.         exp = -exp;
  292.     }
  293. #if IEEE_FP
  294.     while (exp >= 100) {
  295.         val *= mod100;
  296.         exp -= 100;
  297.     }
  298. #endif
  299.     while (exp >= 10) {
  300.         val *= mod10;
  301.         exp -= 10;
  302.     }
  303.     while (exp--)
  304.         val *= mod;        /* slow and dirty */
  305.     t = &curtok;
  306.     t->tnum = FCON;
  307.     t->fval = val;
  308.     sprintf(t->name, FLTFORM, val);
  309. }
  310.  
  311. char *
  312. getname(c)
  313. register int c;
  314. {
  315.     register int nhave;
  316.  
  317.     nhave = 0;
  318.     do {
  319.         if (nhave < MAXSTR)
  320.             curstr[nhave++] = c;
  321.         c = mygetchar();
  322.     } while (isalnum(c) || c == '_');
  323.     myungetc(c);
  324.     curstr[nhave] = 0;
  325.     return curstr;
  326. }
  327.  
  328. static char *holdstr;
  329.  
  330. chr_push(s)
  331. char *s;
  332. {
  333.     holdstr = s;
  334. }
  335.  
  336. static int holdchar, xholdchar;
  337.  
  338. mygetchar()
  339. {
  340.     register int c;
  341.     int c2;
  342.  
  343.     if (holdchar) {
  344.         c = holdchar;
  345.         holdchar = 0;
  346.         goto out;
  347.     }
  348.     if (holdstr) {        /* used for -D args */
  349.         c = *holdstr++;
  350.         if (c == 0) {
  351.             holdstr = NULL;
  352.             return '\n';
  353.         }
  354.         return c;
  355.     }
  356.  
  357. retry:
  358.     c = xgetc();
  359.     if (c == EOF) {
  360.         if (endfile())
  361.             goto retry;
  362.     } else if (c == '\\') {        /* ansi handling of backslash nl */
  363.         c2 = xgetc();
  364.         if (c2 == '\n') {
  365.             lineno++;
  366.             goto retry;
  367.         } else
  368.             xholdchar = c2;
  369.     }
  370. out:
  371.     if (c == '\n') {
  372.         sawnl++;    /* for pre.c */
  373.         lineno++;
  374.     }
  375.     return c;
  376. }
  377.  
  378. xgetc()
  379. {
  380.     register int c;
  381.  
  382.     if (xholdchar) {
  383.         c = xholdchar;
  384.         xholdchar = 0;
  385.         return c;
  386.     }
  387. #if CC68|dLibs
  388.     if (input == stdin)    /* bypass stupid input */
  389.         c = hackgetc();
  390.     else
  391. #endif
  392.         c = getc(input);
  393.     if (c != EOF)
  394.         c &= 0x7f;
  395.     return c;
  396. }
  397.  
  398. myungetc(c)
  399. char c;
  400. {
  401.     if (c != EOF)
  402.         holdchar = c;
  403.     if (c == '\n')
  404.         lineno--;
  405. }
  406.  
  407. struct op {
  408.     char *name;
  409.     char *asname;
  410.     int flags;
  411.     char prec;
  412.     char value;
  413. } ops[] = {
  414.     {"{"},
  415.     {"}"},
  416.     {"["},
  417.     {"]"},
  418.     {"("},
  419.     {")"},
  420.     {"#"},
  421.     {"\\"},
  422.     {";"},
  423.     {","},
  424.     {":"},
  425.     {"."},
  426.  
  427.     {"\"", 0, SPECIAL},
  428.     {"'", 0, SPECIAL},
  429.  
  430.     {"==", 0, C_NOT_A, 5},
  431.     {"=", 0, 0},
  432.  
  433.     {"++", 0, CAN_U},
  434.     {"+", "+=", CAN_AS|C_AND_A, 2},
  435.  
  436.     {"--", 0, CAN_U},
  437.     {"->", 0, 0, 0, ARROW},
  438.     {"-", "-=", CAN_U|CAN_AS, 2},
  439.  
  440.     {"*", "*=", CAN_U|CAN_AS|C_AND_A, 1},
  441.     {"%", "%=", CAN_AS, 1},
  442.  
  443.     {"/*", 0, SPECIAL},
  444.     {"/", "/=", CAN_AS, 1},
  445.  
  446.     {"&&", 0, 0, 9},
  447.     {"&", "&=", CAN_U|CAN_AS|C_AND_A, 6},
  448.  
  449.     {"||", 0, 0, 10},
  450.     {"|", "|=", CAN_AS|C_AND_A, 8},
  451.  
  452.     {"!=", 0, C_NOT_A, 5, NOTEQ},
  453.     {"!", 0, CAN_U},
  454.  
  455.     {"~", 0, CAN_U},
  456.  
  457.     {"^", "^=", CAN_AS|C_AND_A, 7},
  458.  
  459.     {"<<", "<<=", CAN_AS, 3},
  460.     {"<=", 0, C_NOT_A, 4, LTEQ},
  461.     {"<", 0, SPECIAL|C_NOT_A, 4},
  462.  
  463.     {">>", ">>=", CAN_AS, 3},
  464.     {">=", 0, C_NOT_A, 4, GTEQ},
  465.     {">", 0, C_NOT_A, 4},
  466.  
  467.     {"?", 0, 0},
  468.  
  469.     {0, 0, 0}
  470. };
  471.  
  472. #define FIRST_C    '!'
  473. #define LAST_C    0177
  474. struct op *opstart[LAST_C-FIRST_C+1];
  475.  
  476. mo_init()
  477. {
  478.     register struct op *p;
  479.     register c;
  480.  
  481.     for (p=ops; p->name; p++) {
  482.         c = p->name[0];
  483.         if (opstart[c-FIRST_C] == 0)
  484.             opstart[c-FIRST_C] = p;
  485.     }
  486. }
  487.  
  488. matchop(c)
  489. {
  490.     register struct tok *t;
  491.     register struct op *p;
  492.     int nxt;
  493.     int value;
  494.     static first = 0;
  495.  
  496.     t = &curtok;
  497.     nxt = mygetchar();
  498.     value = c;
  499.     if (first == 0) {
  500.         mo_init();
  501.         first = 1;
  502.     }
  503.     p = opstart[c-FIRST_C];
  504.     if (p)
  505.     for (; p->name; p++)
  506.         if (p->name[0] == c)
  507.             if (p->name[1] == 0 || p->name[1] == nxt) {
  508.                 if (p->name[1] == 0)
  509.                     myungetc(nxt);
  510.                 else {
  511.                     value = p->value ? p->value :
  512.                         DOUBLE value;
  513.                 }
  514.                 if (p->flags & SPECIAL)
  515.                     if (c != '<' || 
  516.                       tk_flags & TK_LTSTR)
  517.                         return dospec(p);
  518.                 t->flags = p->flags;
  519.                 if (p->flags & CAN_AS) {
  520.                     nxt = mygetchar();
  521.                     if (nxt != '=') {
  522.                         myungetc(nxt);
  523.                     } else {
  524.                         value = ASSIGN value;
  525.                         t->flags = 0;
  526.                     }
  527.                 }
  528.                 t->name = isassign(value)?p->asname:p->name;
  529.                 t->tnum = value;
  530.                 t->prec = isassign(value)? 0 : p->prec;
  531.                 return 1;
  532.             }
  533.     myungetc(nxt);
  534.     t->name = "???";
  535.     t->tnum = BADTOK;
  536.     return 0;
  537. }
  538.  
  539. dospec(p)
  540. struct op *p;
  541. {
  542.     register struct tok *t;
  543.     register int c;
  544.     int nhave;
  545.     int endc;
  546.  
  547.     t = &curtok;
  548.     switch (p->name[0]) {
  549.     case '/':        /* slash-star */
  550. look:
  551.         do {
  552.             c = mygetchar();
  553.         } while (c != '*');
  554.         c = mygetchar();
  555.         if (c == '/')
  556.             return 0;
  557.         myungetc(c);
  558.         goto look;
  559.     case '\'':
  560.         t->tnum = ICON;
  561.         t->ival = getschar('\''); /* allow only 1 for now*/
  562.         while (getschar('\'') != NOCHAR)
  563.             ;
  564.         sprintf(curstr, "%d", (int)t->ival);
  565.         return 1;
  566.     case '<':
  567.         endc = '>';
  568.         t->tnum = SCON2;
  569.         goto strs;
  570.     case '"':
  571.         endc = '"';
  572.         t->tnum = SCON;
  573.     strs:
  574.         t->name = curstr;
  575.         nhave = 0;
  576.         c = getschar(endc);
  577.         while (c != NOCHAR) {
  578.             if (c >= 0 && c <= 1 && nhave < MAXSTR) {
  579.                  /* allow null */
  580.                 curstr[nhave++] = 1;
  581.                 c++;
  582.             }
  583.             if (nhave < MAXSTR)
  584.                 curstr[nhave++] = c;
  585.             c = getschar(endc);
  586.         }
  587.         curstr[nhave] = 0;
  588.         return 1;
  589.     }
  590. }
  591.  
  592. getoct(c)
  593. {
  594.     char n, i;
  595.  
  596.     n = c - '0';
  597.     for (i=1; i < 3; i++) {
  598.         c = mygetchar();
  599.         if (c < '0' || c > '7') {
  600.             myungetc(c);
  601.             return (int)n;
  602.         }
  603.         n = 8*n + (c - '0');
  604.     }
  605.     return (int)n;
  606. }
  607.     
  608. getschar(del)
  609. char del;
  610. {
  611.     register int c;
  612.  
  613. more:
  614.     c = mygetchar();
  615.     if (c == del)
  616.         return NOCHAR;
  617.     if (c == '\n') {
  618.         error("nl in string");
  619.         myungetc(c);
  620.         return NOCHAR;
  621.     }
  622.     if (c == '\\' && (tk_flags & TK_NOESC) == 0) {
  623.         c = mygetchar();
  624.         if (c == del)
  625.             return c;
  626.         if (c >= '0' && c <= '7')
  627.             return getoct(c);
  628.         switch (c) {
  629. /*
  630.         case '\n':
  631.             goto more;
  632. */
  633.         case 'b':
  634.             c = '\b';
  635.             break;
  636.         case 'n':
  637.             c = '\n';
  638.             break;
  639.         case 't':
  640.             c = '\t';
  641.             break;
  642.         case 'r':
  643.             c = '\r';
  644.             break;
  645.         case 'f':
  646.             c = '\f';
  647.             break;
  648.         }
  649.     }
  650.     return c;
  651. }
  652.  
  653. #ifndef dLibs
  654.  
  655. isalpha(c)
  656. register char c;
  657. {
  658.     if ((c>='a' && c<='z') ||
  659.         (c>='A' && c<='Z'))
  660.         return 1;
  661.     return 0;
  662. }
  663.  
  664. isalnum(c)
  665. register char c;
  666. {
  667.     return (isalpha(c) || (c>='0' && c<='9'));
  668. }
  669.  
  670. tolower(c)
  671. register char c;
  672. {
  673.     if (c>='A' && c<='Z')
  674.         c += 'a'-'A';
  675.     return c;
  676. }
  677.  
  678. #endif
  679.  
  680. ishexa(c)
  681. register char c;
  682. {
  683.     if (c>='a' && c<='f')
  684.         return (c-'a'+10);
  685.     if (c>='A' && c<='F')
  686.         return (c-'A'+10);
  687.     return 0;
  688. }
  689.  
  690. #if CC68
  691. hackgetc()
  692. {
  693.     register int c;
  694.  
  695.     c = bios(2,2);
  696.     switch (c) {
  697.     case 4:
  698.         return EOF;
  699.     case '\r':
  700.     case '\n':
  701.         bios(3,2,'\r');
  702.         bios(3,2,'\n');
  703.         return '\n';
  704.     }
  705.     bios(3,2,c);
  706.     return c;
  707. }
  708. #endif
  709.  
  710. #if dLibs
  711. hackgetc()
  712. {
  713.     register int c;
  714.  
  715.     c = getchar();
  716.     switch (c) {
  717.     case 4:
  718.         return EOF;
  719.     case '\n':
  720.         putchar('\n');
  721.         break;
  722.     }
  723.     return c;
  724. }
  725. #endif
  726.